package com.wwu.system.common.utils;

import cn.hutool.core.date.DateUtil;
import com.wwu.system.entity.*;
import com.wwu.system.entity.server.*;
import org.springframework.stereotype.Component;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.CentralProcessor.TickType;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;

/**
 * 服务器工具类
 * @author 一蓑烟雨
 * @version 1.0.0
 * @date 2022-05-18 11:05
 **/
@Component
public class OshiUtils {
    private static final int OSHI_WAIT_SECOND = 1000;

    SystemInfo si = new SystemInfo();
    HardwareAbstractionLayer hal = si.getHardware();

    /**
     * 获取服务器CPU信息
     * @return: com.wwu.monitor.entity.Cpu
     * @author 一蓑烟雨
     * @date 2022/5/18 0018 下午 12:12
     */
    public Cpu getCpuInfo(){
        CentralProcessor processor = hal.getProcessor();
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        Util.sleep(OSHI_WAIT_SECOND);
        long[] ticks = processor.getSystemCpuLoadTicks();
        long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
        long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
        long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
        long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
        //计算CPU内核态运行时间
        long sysTime = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
        //计算CPU用户态运行时间
        long userTime = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
        //计算CPU等待时间
        long waitTime = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
        //计算CPU空闲时间
        long idleTime = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
        //计算CPU总时间
        long totalTime = userTime + nice + sysTime + idleTime + waitTime + irq + softirq + steal;

        Cpu cpu = new Cpu();
        //CPU核心数
        cpu.setCpuNum(processor.getLogicalProcessorCount());
        //CPU总使用时间
        cpu.setTotalUsedTime(totalTime);
        //CPU系统使用率
        cpu.setSysUsedRate(sysTime);
        //CPU用户使用率
        cpu.setUserUsedRate(userTime);
        //CPU等待率
        cpu.setCpuWaitRate(waitTime);
        //CPU空闲率
        cpu.setCpuIdleRate(idleTime);

        return cpu;
    }

    /**
     * 获取服务器和虚拟机内存信息
     * @return: com.wwu.monitor.entity.Mem
     * @author 一蓑烟雨
     * @date 2022/5/18 0018 下午 12:12
     */
    public Mem getMemInfo(){
        GlobalMemory memory = hal.getMemory();

        Mem mem = new Mem();
        //设置服务器内存
        //内存总大小
        mem.setTotal(memory.getTotal());
        //内存已用大小
        mem.setUsedTotal(memory.getTotal() - memory.getAvailable());
        //内存空闲大小
        mem.setIdleTotal(memory.getAvailable());

        //设置虚拟机内存
        //JVM内存总大小
        mem.setJvmTotal(Runtime.getRuntime().totalMemory());
        //JVM内存已用大小
        mem.setJvmUsedTotal(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
        //JVM内存空闲大小
        mem.setJvmIdleTotal(Runtime.getRuntime().freeMemory());

        return mem;
    }

    /**
     * 获取java虚拟机信息
     * @return: void
     * @author 一蓑烟雨
     * @date 2022/5/18 0018 下午 12:14
     */
    public Jvm getJvmInfo(){
        Jvm jvm = new Jvm();

        Properties props = System.getProperties();
        //JDK名称
        jvm.setJdkName(ManagementFactory.getRuntimeMXBean().getVmName());
        //JDK版本
        jvm.setJdkVersion(props.getProperty("java.version"));
        //JDK安装路径
        jvm.setJdkPath(props.getProperty("java.home"));

        long startTime = ManagementFactory.getRuntimeMXBean().getStartTime();
        //JDK启动时间
        jvm.setJdkStartTime(DateUtil.format(new Date(startTime),"yyyy-MM-dd HH:mm:ss"));
        //JDK运行时长
        jvm.setJdkRunTime(getTimeDiff(new Date(),new Date(startTime)));
        //JDK运行参数
        jvm.setJdkRunArgs(ManagementFactory.getRuntimeMXBean().getInputArguments().toString());

        return jvm;
    }

    /**
     * 获取服务器磁盘信息
     * @return: java.util.List<com.wwu.monitor.entity.Disc>
     * @author 一蓑烟雨
     * @date 2022/5/18 0018 下午 12:17
     */
    public List<Disc> getDiscs(){
        OperatingSystem os = si.getOperatingSystem();
        List<Disc> discs = new LinkedList<Disc>();

        FileSystem fileSystem = os.getFileSystem();
        List<OSFileStore> fsArray = Arrays.asList(fileSystem.getFileStores());
        for (OSFileStore fs : fsArray){
            long idleTotal = fs.getUsableSpace();
            long discTotal = fs.getTotalSpace();
            long usedTotal = discTotal - idleTotal;

            Disc disc = new Disc();
            //盘符路径(名称)
            disc.setDiscName(fs.getMount());
            //盘符类型
            disc.setDiscType(fs.getType());
            //文件类型
            disc.setFileType(fs.getName());
            //总大小
            disc.setDiscTotal(discTotal);
            //空闲大小
            disc.setDiscIdleTotal(idleTotal);
            //已使用大小
            disc.setDiscUsedTotal(usedTotal);

            discs.add(disc);

            //按照盘符名称排序
            Collections.sort(discs,new Comparator<Disc>(){
                @Override
                public int compare(Disc o1, Disc o2) {
                    return o1.getDiscName().compareTo(o2.getDiscName());
                }
            });
        }

        return discs;
    }

    /**
     *  获取服务器操作系统信息
     * @return: com.wwu.monitor.entity.Jvm
     * @author 一蓑烟雨
     * @date 2022/5/18 0018 下午 12:20
     */
    public OperSys getOperSysInfo(){
        OperSys operSys = new OperSys();
        try {
            //服务器名称
            operSys.setServerName(InetAddress.getLocalHost().getHostName());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        try {
            //服务器Ip
            operSys.setServerIp(InetAddress.getLocalHost().getHostAddress());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        //项目路径
        operSys.setProjectPath(System.getProperties().getProperty("user.dir"));
        //操作系统类型
        operSys.setOsName(System.getProperties().getProperty("os.name"));
        //操作系统架构
        operSys.setOsArch(System.getProperties().getProperty("os.arch"));

        return operSys;
    }

    /**
     * 计算2个时间点的间隔，返回天、时、分
     * @param startDate: 开始时间
     * @param endDate: 结束时间
     * @return: java.lang.String
     * @author 一蓑烟雨
     * @date 2022/5/17 0017 下午 21:20
     */
    private static String getTimeDiff(Date startDate, Date endDate){
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - startDate.getTime();
        if(startDate.after(endDate)){
            diff = startDate.getTime() - endDate.getTime();
        }
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }
}
